#ifndef VMINSTR_H
#define VMINSTR_H

#include <QString>

#include "VMExec.h"

namespace CuteVM {

    typedef enum {
        NOOP=1,
        PUSH=2,
        POP=3,
        STORE=4,
        FETCH=5,
        GALLOC=6,
        GSTORE=7,
        GFETCH=8,
        JUMP=9,
        JFALSE=10,
        CALL=11,
        RETURN=12
    } InstrType;

    class Machine;

    class Instruction {
    private:
        ExecError err;
        ExecSuccess succ;
    protected:
        Instruction() : err(ExecError(NULL,*this,"no error")), succ(ExecSuccess(NULL,*this)) {}
        ExecError & error(Machine * vm, QString message) {
            err.setMachine(vm);
            err.setMessage(message);
            return err;
        }

        ExecSuccess & success(Machine *vm, Value * value = NULL) {
            succ.setMachine(vm);
            succ.setValue(value);
            return succ;
        }

    public:
        virtual InstrType getType() = 0;
        virtual ExecResult & exec(Machine *vm) = 0;
        virtual QString toString() = 0 ;
    };

    class Noop : public Instruction {
    public:
        Noop() : Instruction() { }
        InstrType getType() { return NOOP; }
        QString toString() { return QString("NOOP"); }
        ExecResult & exec(Machine *vm);
    };

    class Push : public Instruction {
    private:
        Value * value;
    public:
        Push(Value *value) : value(value), Instruction() { }
        InstrType getType() { return PUSH; }
        QString toString();
        ExecResult & exec(Machine *vm);
    };

    class Pop : public Instruction {
    public:
        Pop() : Instruction() { }
        InstrType getType() { return POP; }
        QString toString();
        ExecResult & exec(Machine *vm);
    };

} // namespace CuteVM

#endif // VMINSTR_H
